Improve date/timestamp handling performance in GenericDaoBase and DateUtil - #13809
Improve date/timestamp handling performance in GenericDaoBase and DateUtil#13809sudo87 wants to merge 2 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## 4.20 #13809 +/- ##
=========================================
Coverage 16.26% 16.27%
- Complexity 13434 13448 +14
=========================================
Files 5667 5667
Lines 500731 500740 +9
Branches 60803 60806 +3
=========================================
+ Hits 81455 81486 +31
+ Misses 410172 410146 -26
- Partials 9104 9108 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@blueorangutan package |
|
@sudo87 a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress. |
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 18782 |
|
looks good @sudo87. |
|
@blueorangutan package |
|
@sudo87 a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress. |
There was a problem hiding this comment.
Pull request overview
This PR improves date/timestamp handling performance by removing string-based JDBC interactions for temporal values, modernizing DateUtil formatting/parsing internals, and avoiding unnecessary CIDR allow-list lookups when that check is disabled.
Changes:
- Switch
GenericDaoBasedate/calendar JDBC reads/writes from string conversions to typedgetTimestamp/setTimestamp/setDate/setTime(with a per-call GMTCalendar). - Replace
DateUtil’s per-callSimpleDateFormatusage with cached, thread-safeDateTimeFormatterinstances. - Optimize
ApiServerCIDR allow-list enforcement by skipping account/CIDR lookup entirely when the feature flag is disabled, and add tests for the new behavior.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| utils/src/main/java/com/cloud/utils/DateUtil.java | Introduces cached DateTimeFormatter usage and updates date parsing/formatting paths. |
| utils/src/test/java/com/cloud/utils/DateUtilTest.java | Adds tests covering DateUtil parsing/formatting behavior across time zones and null handling. |
| framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java | Migrates JDBC temporal reads/writes to typed APIs and adds GMT Calendar helper + temporal SQL type selection. |
| framework/db/src/test/java/com/cloud/utils/db/GenericDaoBaseTest.java | Adds unit tests validating GMT calendar behavior and typed timestamp reads for Date/Calendar. |
| server/src/main/java/com/cloud/api/ApiServer.java | Skips CIDR allow-list lookup when checks are disabled; uses whitespace deletion helper. |
| server/src/test/java/com/cloud/api/ApiServerTest.java | Adds tests validating CIDR lookup skip/allow/deny paths and restores config defaults after each test. |
| engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java | Changes date mapping from TemporalType.DATE to TemporalType.TIMESTAMP. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| private static DateTimeFormatter getFormatter(String pattern, ZoneId zone) { | ||
| String key = pattern + "|" + zone.getId(); | ||
| DateTimeFormatter formatter = s_formatterCache.get(key); | ||
| if (formatter == null) { | ||
| formatter = DateTimeFormatter.ofPattern(pattern).withZone(zone); | ||
| DateTimeFormatter existing = s_formatterCache.putIfAbsent(key, formatter); | ||
| if (existing != null) { | ||
| return existing; | ||
| } | ||
| } | ||
| return formatter; | ||
| } |
|
Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 18788 |
Description
This PR contains following changes:
GenericDaoBase was reading and writing dates by converting them to strings via DateUtil and passing those strings to JDBC.
This means every single DB read or write for a date column allocates a string, formats it, and then parses it back on the other side - completely unnecessary work the JDBC driver can handle natively.
This PR replaces all of that with proper JDBC typed methods: getTimestamp() for reads, and setTimestamp()/setDate()/setTime() for writes, using a per-call GMT Calendar so timezone handling stays consistent.
Cleaned up
DateUtil:SimpleDateFormatisn't thread-safe and was allocated fresh percall. Swapped in
DateTimeFormatter, cached in aConcurrentHashMapkeyed by pattern + zone,so formatting is just a map lookup now.
Also, includes a minor optimization to the CIDR allow-list check in
ApiServer(lookup is now skipped entirely when the check is disabled).Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):
How Has This Been Tested?
How did you try to break this feature and the system with this change?